import random
import time
import re
from datetime import datetime


class BankSystem:
    def __init__(self):
        # 管理员账号密码
        self.admin_user = "admin"
        self.admin_pwd = "12345"  # 实际应用中应存储加密后的密码
        # 存储用户信息：{卡号: {姓名, 身份证号, 手机号, 余额, 密码, 锁定状态, 开户时间}}
        self.users = {}
        # 已生成的卡号集合
        self.card_numbers = set()
        # 交易记录
        self.transaction_records = {}
    def admin_login(self):
        print("=" * 40)
        print("         欢迎登录银行管理系统 V2.0")
        print("=" * 40)

        retry_count = 3
        while retry_count > 0:
            user = input("请输入管理员账户: ").strip()
            pwd = input("请输入密码: ").strip()

            if user == self.admin_user and pwd == self.admin_pwd:
                print("登录成功，正在加载系统...")
                time.sleep(1)
                self.show_menu()
                return

            retry_count -= 1
            if user != self.admin_user:
                print(f"管理员账户不存在！剩余{retry_count}次机会")
            else:
                print(f"密码错误！剩余{retry_count}次机会")

            time.sleep(0.5)

        print("登录失败次数过多，系统将退出！")
        time.sleep(1)
        exit()

    def show_menu(self):
        """显示功能菜单（优化布局和提示）"""
        while True:
            print("\n" + "*" * 40)
            print("**        银行管理系统功能菜单        **")
            print("**  1.开户(1)        2.查询余额(2)    **")
            print("**  3.取款(3)        4.存款(4)        **")
            print("**  5.转账(5)        6.锁定账户(6)    **")
            print("**  7.解锁账户(7)    8.查询交易记录(8)**")
            print("**  9.修改密码(9)                    **")
            print("**           0.退出系统(0)            **")
            print("*" * 40)

            choice = input("请输入功能编号选择操作: ").strip()
            if choice == "1":
                self.open_account()
            elif choice == "2":
                self.query_balance()
            elif choice == "3":
                self.withdraw()
            elif choice == "4":
                self.deposit()
            elif choice == "5":
                self.transfer()
            elif choice == "6":
                self.lock_account()
            elif choice == "7":
                self.unlock_account()
            elif choice == "8":
                self.query_transactions()
            elif choice == "9":
                self.change_password()
            elif choice == "0":
                self.exit_system()
            else:
                print("输入错误！请输入0-9之间的功能编号")
                time.sleep(0.5)

    def generate_card(self):
        """生成8位不重复卡号（提升安全性）"""
        while True:
            # 前2位固定为62（模拟银联卡号前缀），后6位随机
            card = "62" + str(random.randint(100000, 999999))
            if card not in self.card_numbers:
                self.card_numbers.add(card)
                return card

    def validate_id_card(self, id_card):
        """验证身份证号格式（18位）"""
        pattern = r'^\d{17}[\dXx]$'
        return re.match(pattern, id_card) is not None

    def validate_phone(self, phone):
        """验证手机号格式（11位）"""
        pattern = r'^\d{11}$'
        return re.match(pattern, phone) is not None
    def validate_password(self, pwd):
        """验证密码格式（6位数字）"""
        pattern = r'^\d{6}$'
        return re.match(pattern, pwd) is not None
    def open_account(self):
        """开户功能（增加输入验证和开户时间记录）"""
        print("\n===== 账户开户 =====")

        # 姓名验证
        while True:
            name = input("请输入姓名: ").strip()
            if name and not name.isdigit():
                break
            print("姓名不能为空且不能为纯数字！")

        # 身份证号验证
        while True:
            id_card = input("请输入18位身份证号: ").strip()
            if self.validate_id_card(id_card):
                break
            print("身份证号格式错误！请输入18位数字或最后一位为X")

        # 手机号验证
        while True:
            phone = input("请输入11位手机号: ").strip()
            if self.validate_phone(phone):
                break
            print("手机号格式错误！请输入11位数字")

        # 预存金额验证
        while True:
            try:
                balance = float(input("请输入预存金额（最低1元）: "))
                if balance >= 1:
                    break
                print("预存金额不能低于1元！")
            except ValueError:
                print("输入错误！请输入有效的数字")

        # 密码验证（6位数字）
        while True:
            pwd = input("请设置6位数字密码: ").strip()
            if self.validate_password(pwd):
                confirm_pwd = input("请确认密码: ").strip()
                if confirm_pwd == pwd:
                    break
                print("两次密码输入不一致！")
            else:
                print("密码格式错误！请输入6位数字")

        # 生成卡号并存储信息
        card = self.generate_card()
        open_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.users[card] = {
            "name": name,
            "id_card": id_card,
            "phone": phone,
            "balance": round(balance, 2),
            "pwd": pwd,
            "locked": False,
            "open_time": open_time
        }
        # 初始化交易记录
        self.transaction_records[card] = [
            (open_time, "开户预存", balance, round(balance, 2))
        ]

        print(f"\n开户成功！")
        print(f"您的卡号: {card}")
        print(f"开户时间: {open_time}")
        print(f"当前余额: {balance:.2f}元")
        print("请妥善保管您的卡号和密码！")
        time.sleep(2)

    def get_user_by_card(self, card):
        """根据卡号获取用户信息（基础验证）"""
        if not card.isdigit() or len(card) != 8:
            print("卡号格式错误！请输入8位数字卡号")
            return None
        if card not in self.users:
            print("卡号不存在！")
            return None
        return self.users[card]

    def verify_card_password(self, card):
        """验证卡号和密码（独立方法，优化逻辑）"""
        user = self.get_user_by_card(card)
        if not user:
            return None

        # 检查锁定状态
        if user["locked"]:
            print("该账户已被锁定！请联系管理员解锁")
            return None

        # 密码验证（3次机会）
        error_count = 0
        while error_count < 3:
            pwd = input("请输入密码: ").strip()
            if user["pwd"] == pwd:
                return user
            error_count += 1
            remaining = 3 - error_count
            if remaining > 0:
                print(f"密码错误！剩余{remaining}次机会")
            else:
                user["locked"] = True
                print("密码错误次数过多，账户已锁定！")
        return None

    def record_transaction(self, card, trans_type, amount, balance):
        """记录交易记录"""
        time_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.transaction_records[card].append(
            (time_str, trans_type, round(amount, 2), round(balance, 2))
        )

    def query_balance(self):
        """查询余额（优化提示信息）"""
        print("\n===== 余额查询 =====")
        card = input("请输入卡号: ").strip()
        user = self.verify_card_password(card)
        if user:
            print(f"\n账户信息：")
            print(f"姓名: {user['name']}")
            print(f"卡号: {card}")
            print(f"当前余额: {user['balance']:.2f}元")
        time.sleep(1.5)

    def withdraw(self):
        """取款功能（优化金额验证和交易记录）"""
        print("\n===== 账户取款 =====")
        card = input("请输入卡号: ").strip()
        user = self.verify_card_password(card)
        if not user:
            time.sleep(1)
            return

        # 取款金额验证
        while True:
            try:
                amount = float(input("请输入取款金额: ").strip())
                if amount <= 0:
                    print("取款金额不能为0或负数！")
                elif amount > user["balance"]:
                    print(f"余额不足！当前余额: {user['balance']:.2f}元")
                elif amount % 100 != 0 and amount < 100:
                    # 模拟ATM取款规则：100元以下不限，100元以上需为100的倍数
                    confirm = input("取款金额不是100元的倍数，是否继续？(y/n): ").strip().lower()
                    if confirm == "y":
                        break
                else:
                    break
            except ValueError:
                print("输入错误！请输入有效的数字")

        # 执行取款
        user["balance"] -= amount
        self.record_transaction(card, "取款", amount, user["balance"])
        print(f"\n取款成功！")
        print(f"取款金额: {amount:.2f}元")
        print(f"当前余额: {user['balance']:.2f}元")
        time.sleep(1.5)

    def deposit(self):
        """存款功能（优化金额验证和交易记录）"""
        print("\n===== 账户存款 =====")
        card = input("请输入卡号: ").strip()
        user = self.verify_card_password(card)
        if not user:
            time.sleep(1)
            return

        # 存款金额验证
        while True:
            try:
                amount = float(input("请输入存款金额: ").strip())
                if amount <= 0:
                    print("存款金额不能为0或负数！")
                else:
                    break
            except ValueError:
                print("输入错误！请输入有效的数字")

        # 执行存款
        user["balance"] += amount
        self.record_transaction(card, "存款", amount, user["balance"])
        print(f"\n存款成功！")
        print(f"存款金额: {amount:.2f}元")
        print(f"当前余额: {user['balance']:.2f}元")
        time.sleep(1.5)

    def transfer(self):
        """转账功能（增加转入账户验证和二次确认）"""
        print("\n===== 账户转账 =====")

        # 转出账户验证
        from_card = input("请输入转出卡号: ").strip()
        from_user = self.verify_card_password(from_card)
        if not from_user:
            time.sleep(1)
            return

        # 转入账户验证
        while True:
            to_card = input("请输入转入卡号: ").strip()
            if to_card == from_card:
                print("不能向自己的账户转账！")
                continue
            to_user = self.get_user_by_card(to_card)
            if to_user:
                if to_user["locked"]:
                    print("转入账户已被锁定！")
                    time.sleep(1)
                    return
                # 显示转入账户姓名（脱敏处理）
                name = to_user["name"]
                hidden_name = name[0] + "*" * (len(name) - 1) if len(name) > 1 else name
                print(f"转入账户姓名: {hidden_name}（请确认信息无误）")
                confirm = input("是否确认该转入账户？(y/n): ").strip().lower()
                if confirm == "y":
                    break
            else:
                retry = input("转入卡号不存在，是否重新输入？(y/n): ").strip().lower()
                if retry != "y":
                    print("转账已取消！")
                    time.sleep(1)
                    return

        # 转账金额验证
        while True:
            try:
                amount = float(input("请输入转账金额: ").strip())
                if amount <= 0:
                    print("转账金额不能为0或负数！")
                elif amount > from_user["balance"]:
                    print(f"余额不足！当前余额: {from_user['balance']:.2f}元")
                else:
                    break
            except ValueError:
                print("输入错误！请输入有效的数字")

        # 最终确认
        confirm = input(f"\n确认向卡号{to_card}转账{amount:.2f}元？(y/n): ").strip().lower()
        if confirm != "y":
            print("转账已取消！")
            time.sleep(1)
            return

        # 执行转账
        from_user["balance"] -= amount
        to_user["balance"] += amount
        # 记录交易记录
        self.record_transaction(from_card, f"转账支出（对方卡号：{to_card[-4:]}）", amount, from_user["balance"])
        self.record_transaction(to_card, f"转账收入（对方卡号：{from_card[-4:]}）", amount, to_user["balance"])

        print(f"\n转账成功！")
        print(f"转账金额: {amount:.2f}元")
        print(f"当前余额: {from_user['balance']:.2f}元")
        time.sleep(2)

    def lock_account(self):
        """锁定账户（优化验证逻辑）"""
        print("\n===== 账户锁定 =====")
        card = input("请输入卡号: ").strip()
        user = self.verify_card_password(card)
        if user:
            if user["locked"]:
                print("该账户已处于锁定状态！")
            else:
                user["locked"] = True
                print("账户锁定成功！")
        time.sleep(1)

    def unlock_account(self):
        """解锁账户（增加身份验证，提升安全性）"""
        print("\n===== 账户解锁 =====")
        card = input("请输入卡号: ").strip()
        user = self.get_user_by_card(card)
        if not user:
            time.sleep(1)
            return

        if not user["locked"]:
            print("该账户未被锁定！")
            time.sleep(1)
            return

        # 身份验证（身份证号后4位）
        id_last4 = input("请输入身份证号后4位进行验证: ").strip()
        if not user["id_card"].endswith(id_last4):
            print("身份验证失败！")
            time.sleep(1)
            return

        # 密码验证
        pwd = input("请输入账户密码: ").strip()
        if user["pwd"] == pwd:
            user["locked"] = False
            print("账户解锁成功！")
        else:
            print("密码错误，解锁失败！")
        time.sleep(1)

    def query_transactions(self):
        """查询交易记录（新增功能）"""
        print("\n===== 交易记录查询 =====")
        card = input("请输入卡号: ").strip()
        user = self.verify_card_password(card)
        if not user:
            time.sleep(1)
            return

        records = self.transaction_records[card]
        if not records:
            print("暂无交易记录！")
            time.sleep(1)
            return

        # 按时间倒序显示（最新的在前）
        print(f"\n{user['name']}（卡号：{card}）的交易记录：")
        print("-" * 80)
        print(f"{'交易时间':<20} {'交易类型':<30} {'交易金额(元)':<15} {'余额(元)':<10}")
        print("-" * 80)
        for record in reversed(records):
            time_str, trans_type, amount, balance = record
            print(f"{time_str:<20} {trans_type:<30} {amount:<15.2f} {balance:<10.2f}")
        print("-" * 80)
        time.sleep(3)

    def change_password(self):
        """修改密码（新增功能）"""
        print("\n===== 密码修改 =====")
        card = input("请输入卡号: ").strip()
        user = self.verify_card_password(card)
        if not user:
            time.sleep(1)
            return

        # 输入新密码
        while True:
            new_pwd = input("请输入新密码（6位数字）: ").strip()
            if not self.validate_password(new_pwd):
                print("新密码格式错误！请输入6位数字")
                continue

            confirm_pwd = input("请确认新密码: ").strip()
            if new_pwd != confirm_pwd:
                print("两次密码输入不一致！")
                continue

            if new_pwd == user["pwd"]:
                print("新密码不能与原密码相同！")
                continue

            break

        # 确认修改
        confirm = input("确认修改密码？(y/n): ").strip().lower()
        if confirm == "y":
            user["pwd"] = new_pwd
            self.record_transaction(card, "修改密码", 0, user["balance"])
            print("密码修改成功！请重新登录")
        else:
            print("密码修改已取消！")
        time.sleep(1.5)

    def exit_system(self):
        """退出系统（优化验证逻辑）"""
        print("\n===== 退出系统 =====")
        confirm = input("确认要退出银行管理系统吗？(y/n): ").strip().lower()
        if confirm != "y":
            print("已取消退出！")
            time.sleep(0.5)
            return

        # 管理员验证
        user = input("请输入管理员账户: ").strip()
        pwd = input("请输入管理员密码: ").strip()
        if user == self.admin_user and pwd == self.admin_pwd:
            print("退出验证成功，正在关闭系统...")
            time.sleep(1)
            print("感谢使用银行管理系统，再见！")
            exit()
        else:
            print("管理员验证失败，无法退出！")
            time.sleep(1)


if __name__ == "__main__":
    # 设置随机种子，保证卡号生成的随机性（可选）
    random.seed(time.time())
    bank = BankSystem()
    bank.admin_login()